/*
 * LDIR
 * 
 * LDIR, a GPS cartography application built for Let's Do It Romania eco 
 * campaign.
 * Copyright (C) 2010 Genera Software <office@generasoftware.com>
 * 
 * http://generasoftware.com/
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 */
#ifndef VALUE_H
#define VALUE_H

// INCLUDES
// System Includes
#include <e32base.h>  // CBase, link against euser.lib
#include "Interfaces.h"


enum Entity_type{ obj_type, array_type, pair_type, str_type, bool_type, int_type, real_type, null_type };

class CPair;
class CEntity;

typedef CArrayPtr<CEntity> Entities;


typedef union _VALUES
{
	TInt		i;          
	TBool		b;     
	TReal		real;        
	HBufC8*		iHbuf8;
	CPair*		iPair;
	Entities*	iEntities;
} __UVALUES;


class CEntity : public CBase, public MSerializable
{
public:

	CEntity(Entity_type aType);  // creates null value
	IMPORT_C ~CEntity();
	IMPORT_C static CEntity* NewL(Entity_type aType);
	IMPORT_C static CEntity* NewLC(Entity_type aType);

	IMPORT_C void SetValueL( const char*	value ); 
	IMPORT_C void SetValueL( const TDesC8&  value );
	IMPORT_C void SetValueL( TInt           value );
	IMPORT_C void SetValueL( bool			value );
	IMPORT_C void SetValueL( TReal          value );
	IMPORT_C void SetValueL( CPair*			value );
	IMPORT_C void SetValueL( Entities*		value );
	IMPORT_C TBool operator==( const CEntity& lhs ) const;

	IMPORT_C TInt Type() const;
	IMPORT_C void AddChildL(CEntity* aChild);
	IMPORT_C CEntity* Parent();
	IMPORT_C void SetParent(CEntity* aParent);
	IMPORT_C void ExternalizeL(RWriteStream& aStream) const;
	IMPORT_C void InternalizeL(RReadStream& aStream);
	IMPORT_C TBool IsRoot() const;
	
	IMPORT_C const TDesC8&		GetStr()   const;
	IMPORT_C Entities*			GetArray() const;
	IMPORT_C bool				GetBool()  const;
	IMPORT_C TInt				GetInt()   const;
	IMPORT_C TReal				GetReal()  const;
	IMPORT_C CPair*				GetPair()	const;
	IMPORT_C CEntity*			GetEntity(TInt aKeyNameIndex) const;
	IMPORT_C void				DeleteEntity(TInt aKeyNameIndex);
	IMPORT_C TInt 				Size() const;
	IMPORT_C CEntity*			CloneL() const;
	
	template< typename T > T GetValue() const;  // example usage: int    i = value.get_value< int >();
	// or             double d = value.get_value< double >();

private:
	TInt iType;
	_VALUES iVariant;
	CEntity* iParent;
};

class CPair : public CBase, public MSerializable
{
public:
	CPair();
	IMPORT_C ~CPair();
	IMPORT_C static CPair* NewL(TInt aFieldIndex, CEntity* aValue);
	IMPORT_C static CPair* NewL();
	IMPORT_C TBool operator==( const CPair& lhs ) const;
	IMPORT_C void SetKeyL(TInt aFieldIndex);
	IMPORT_C void SetValue(CEntity* aValue);
	IMPORT_C void ExternalizeL(RWriteStream& aStream) const;
	IMPORT_C void InternalizeL(RReadStream& aStream);
	IMPORT_C TInt Size() const;
	
public: // Data
	TInt iFieldIndex; // index of the field name in the string pool table
	CEntity* iValue;
};


namespace internal_
{
	template< typename T >
	struct Type_to_type
	{
	};

	template< class CEntity > 
		TInt get_value( const CEntity& value, Type_to_type< TInt > )
	{
		return value.GetInt();
	}

	template< class CEntity > 
		TReal get_value( const CEntity& value, Type_to_type< TReal > )
	{
		return value.GetReal();
	}

	template< class CEntity > 
		const TDesC8& get_value( const CEntity& value, Type_to_type< const TDesC8& > )
	{
		return value.GetStr();
	}

	template< class CEntity > 
		Entities* get_value( const CEntity& value, Type_to_type< Entities > )
	{
		return value.GetArray();
	}

	template< class CEntity > 
		bool get_value( const CEntity& value, Type_to_type< bool > )
	{
		return value.GetBool();
	}
}

template< typename T > 
T CEntity::GetValue() const
{
	return internal_::get_value( *this, internal_::Type_to_type< T >() );
}


#endif // VALUE_H

// End of File
